package com.landian.commons.jpa.hql;


import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * AbstractPageHql
 *
 * @author caojl
 * @create 2017/12/04
 **/
public abstract class AbstractListHql implements ListHql {

    private List<QueryPart> queryPartList = new ArrayList<>();

    private String and(){
        return " and ";
    }

    private String whereSupport(){
        return " where 1=1 ";
    }

    protected void addQueryPart(QueryPart queryPart){
        queryPartList.add(queryPart);
    }

    @Override
    public String selectHQL() {
        addQueryPartInvoke();
        return buildHQL(selectPart(), false);
    }

    @Override
    public List<QueryPart> getQueryPart() {
        return queryPartList;
    }

    /**
     * addQueryPartInvoke钩子
     */
    protected void addQueryPartInvoke() {}

    protected String buildHQL(String select, boolean countSQL) {
        StringBuffer sb = new StringBuffer();
        sb.append("select " + select + " ");
        sb.append(fromPart() + " ");
        sb.append(whereSupport());
        // 处理where
        List<String> joinList = join();
        if(CollectionUtils.isNotEmpty(joinList)){
            String joinHql = StringUtils.join(joinList, " and ");
            sb.append(" " + and() + joinHql);
        }
        List<QueryPart> queryPartList = getQueryPart();
        if(CollectionUtils.isNotEmpty(queryPartList)){
            List<PredicateHql> predicateHqlList = queryPartList.stream().map(b -> b.getPredicateHql()).collect(Collectors.toList());
            for(PredicateHql predicateHql : predicateHqlList){
                if(null != predicateHql){
                    String hql = predicateHql.hql();
                    sb.append(" " + and() + hql);
                }
            }
        }
        if(!countSQL && StringUtils.isNotBlank(orderPart())){
            sb.append(" order by " + orderPart());
        }
        return sb.toString();
    }
}
